#ifndef __VM_TYPES__
#define __VM_TYPES__

#include <winnt.h>

namespace xm
{
#define if_not(x)		if( !(x) ) 

	typedef size_t		bool_t;

	static bool operator < ( const std::string & left, const std::string & right )
	{
		return stricmp( left.c_str(), right.c_str() ) < 0;
	}

	static const vxvma_t	MINI_CORE_BASE32		= 0x70000000;
	static const vxvma_t	MINI_CORE_BASE64		= 0x7FFF70000000LL;
	static const vxvma_t	PROC32_USER_TOP			= 0x80000000LL;
	static const vxvma_t	PROC64_USER_TOP			= 0x800000000000LL;
	static const vxvma_t	PROC64_USER_SHARE_DATA	= 0x7FFE0000LL;
	static const vxvma_t	PROC32_USER_SHARE_DATA	= 0x7FFE0000;


	enum { VM_PAGE_SHIFT = 12 };
	enum { VM_PAGE_SIZE = 0x1000 };
	enum { VM_PAGE_MASK = (VM_PAGE_SIZE-1) };

	struct seginfo_t
	{
		uint64_t offset;
		uint64_t bytes;
		uint32_t paga;
	};

#ifdef _WIN64
	enum { SIZE_OF_80387_REGISTERS = 80 };
	enum { MAXIMUM_SUPPORTED_EXTENSION = 512 };
#endif

	typedef struct _FLOATING_SAVE_AREA
	{
		DWORD   ControlWord;
		DWORD   StatusWord;
		DWORD   TagWord;
		DWORD   ErrorOffset;
		DWORD   ErrorSelector;
		DWORD   DataOffset;
		DWORD   DataSelector;
		BYTE	RegisterArea[SIZE_OF_80387_REGISTERS];
		DWORD   Cr0NpxState;
	} FLOATING_SAVE_AREA;


	//
	// Format of data for (F)XSAVE/(F)XRSTOR instruction
	//

	typedef struct DECLSPEC_ALIGN(16) _XSAVE_FORMAT {
		WORD	ControlWord;
		WORD	StatusWord;
		BYTE	TagWord;
		BYTE	Reserved1;
		WORD	ErrorOpcode;
		DWORD	ErrorOffset;
		WORD	ErrorSelector;
		WORD	Reserved2;
		DWORD DataOffset;
		WORD   DataSelector;
		WORD   Reserved3;
		DWORD MxCsr;
		DWORD MxCsr_Mask;
		M128A FloatRegisters[8];

#if 1

		M128A XmmRegisters[16];
		BYTE  Reserved4[96];

#else

		M128A XmmRegisters[8];
		BYTE  Reserved4[220];

		//
		// Cr0NpxState is not a part of XSAVE/XRSTOR format. The OS is relying on
		// a fact that neither (FX)SAVE nor (F)XSTOR uses this area.
		//

		DWORD   Cr0NpxState;

#endif

	} XSAVE_FORMAT, *PXSAVE_FORMAT;



	struct CONTEXTX86
	{
		//
		// The flags values within this flag control the contents of
		// a CONTEXT record.
		//
		// If the context record is used as an input parameter, then
		// for each portion of the context record controlled by a flag
		// whose value is set, it is assumed that that portion of the
		// context record contains valid context. If the context record
		// is being used to modify a threads context, then only that
		// portion of the threads context will be modified.
		//
		// If the context record is used as an IN OUT parameter to capture
		// the context of a thread, then only those portions of the thread's
		// context corresponding to set flags will be returned.
		//
		// The context record is never used as an OUT only parameter.
		//

		DWORD ContextFlags;

		//
		// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
		// set in ContextFlags.  Note that CONTEXT_DEBUG_REGISTERS is NOT
		// included in CONTEXT_FULL.
		//

		DWORD   Dr0;
		DWORD   Dr1;
		DWORD   Dr2;
		DWORD   Dr3;
		DWORD   Dr6;
		DWORD   Dr7;

		//
		// This section is specified/returned if the
		// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
		//

		FLOATING_SAVE_AREA FloatSave;

		//
		// This section is specified/returned if the
		// ContextFlags word contians the flag CONTEXT_SEGMENTS.
		//

		DWORD   SegGs;
		DWORD   SegFs;
		DWORD   SegEs;
		DWORD   SegDs;

		//
		// This section is specified/returned if the
		// ContextFlags word contians the flag CONTEXT_INTEGER.
		//

		DWORD   Edi;
		DWORD   Esi;
		DWORD   Ebx;
		DWORD   Edx;
		DWORD   Ecx;
		DWORD   Eax;

		//
		// This section is specified/returned if the
		// ContextFlags word contians the flag CONTEXT_CONTROL.
		//

		DWORD   Ebp;
		DWORD   Eip;
		DWORD   SegCs;			  // MUST BE SANITIZED
		DWORD   EFlags;			 // MUST BE SANITIZED
		DWORD   Esp;
		DWORD   SegSs;

		//
		// This section is specified/returned if the ContextFlags word
		// contains the flag CONTEXT_EXTENDED_REGISTERS.
		// The format and contexts are processor specific
		//

		BYTE	ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];

	};
	
	typedef XSAVE_FORMAT XMM_SAVE_AREA32, *PXMM_SAVE_AREA32;

	typedef struct CONTEXTX64
	{
		//
		// Register parameter home addresses.
		//
		// N.B. These fields are for convience - they could be used to extend the
		//	  context record in the future.
		//

		DWORD64 P1Home;
		DWORD64 P2Home;
		DWORD64 P3Home;
		DWORD64 P4Home;
		DWORD64 P5Home;
		DWORD64 P6Home;

		//
		// Control flags.
		//

		DWORD ContextFlags;
		DWORD MxCsr;

		//
		// Segment Registers and processor flags.
		//

		WORD   SegCs;
		WORD   SegDs;
		WORD   SegEs;
		WORD   SegFs;
		WORD   SegGs;
		WORD   SegSs;
		DWORD EFlags;

		//
		// Debug registers
		//

		DWORD64 Dr0;
		DWORD64 Dr1;
		DWORD64 Dr2;
		DWORD64 Dr3;
		DWORD64 Dr6;
		DWORD64 Dr7;

		//
		// Integer registers.
		//

		DWORD64 Rax;
		DWORD64 Rcx;
		DWORD64 Rdx;
		DWORD64 Rbx;
		DWORD64 Rsp;
		DWORD64 Rbp;
		DWORD64 Rsi;
		DWORD64 Rdi;
		DWORD64 R8;
		DWORD64 R9;
		DWORD64 R10;
		DWORD64 R11;
		DWORD64 R12;
		DWORD64 R13;
		DWORD64 R14;
		DWORD64 R15;

		//
		// Program counter.
		//

		DWORD64 Rip;

		//
		// Floating point state.
		//

		union {
			XMM_SAVE_AREA32 FltSave;
			struct {
				M128A Header[2];
				M128A Legacy[8];
				M128A Xmm0;
				M128A Xmm1;
				M128A Xmm2;
				M128A Xmm3;
				M128A Xmm4;
				M128A Xmm5;
				M128A Xmm6;
				M128A Xmm7;
				M128A Xmm8;
				M128A Xmm9;
				M128A Xmm10;
				M128A Xmm11;
				M128A Xmm12;
				M128A Xmm13;
				M128A Xmm14;
				M128A Xmm15;
			} DUMMYSTRUCTNAME;
		} DUMMYUNIONNAME;

		//
		// Vector registers.
		//

		M128A VectorRegister[26];
		DWORD64 VectorControl;

		//
		// Special debug control registers.
		//

		DWORD64 DebugControl;
		DWORD64 LastBranchToRip;
		DWORD64 LastBranchFromRip;
		DWORD64 LastExceptionToRip;
		DWORD64 LastExceptionFromRip;
	} CONTEXTX64;

};


#endif